/* Janus Chat - Version 1.0
 * Authors: Matthew Perry
 *          Michael Freid
 *          Marc Latou
 *          Richard Lee
 *
 * The Janus Chat Client is a highly secured
 * peer-to-peer chat client designed to facilitate
 * the transfer of sensitive data or as a communication
 * medium for the extra paranoid
 *
 * This file contains the headers for a set of exception
 * classes which our other classes can use for error reporting
 * and handling */

#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H

#include <string>
#include <errno.h>

using std::string;

/* These two classes, as well as the classes in unix_exceptions.h
 * utilize the design pattern, Template Method. The class
 * BaseException, is the abstract base that all other exceptions
 * in this sytem derive from. The errorString() function is virtual
 * and is defined in the subclasses. This function is called by
 * the BaseException's what() function. The wantErrno function
 * is used as a hook to allow subclasses to opt-out of the
 * errorString functionality() */

class BaseException
{
    private:
        string myStr;           /* String to store error message */

    protected:
        /* Virtual function which returns a friendly error message
         * about the error that occured */
        virtual string errorString() const { return ""; }

        /* Optional virtual function which asks if the subclass
         * would like the system info on the error */
        virtual bool wantErrno() const { return true; }

    public:
        BaseException( const string& str ) { myStr = str; }
        ~BaseException() throw() {}

        /* This function returns a string that is displayed
         * when the exception is caught. If the sub class does
         * not need system info then it simply returns what
         * was given to the constructor. Otherwise it appends
         * system info to what was given to the constructor */
        string what() const throw()
        {
            string retval = myStr;
            if( wantErrno() )  //Does the subclass need this?
            {
                string delimiter( ": " );
                retval += delimiter + errorString();
            }
            return retval;
        }
};

class MessageException : public BaseException
{
    protected:
        /* Here we reimplement the wantErrno() function because
         * the message class is purely one of our classes so
         * no system information is provided when it crashes */
        bool wantErrno() const { return false; }

    public:
        MessageException( const string& str )
            : BaseException( str ) {}
        ~MessageException() throw () {}
};

#endif
